package com.sidecar.service.log.config;

import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;

import com.sidecar.service.log.web.OperationLogController;
import com.sidecar.service.log.web.StatusChangeLogController;

import io.undertow.UndertowOptions;
import reactor.ipc.netty.http.server.HttpServer;

import static org.springframework.web.reactive.function.server.RequestPredicates.*;
import static org.springframework.web.reactive.function.server.RouterFunctions.*;

import javax.annotation.Resource;

@Configuration
@EnableWebFlux
public class RoutingConfiguration {

    @Resource
    Environment environment;

    @Resource
    OperationLogController operationLogController;

    @Resource
    StatusChangeLogController statusChangeLogController;

    @Bean
    public RouterFunction<?> routerFunction() {
        return nest(path("/operationLog"),
                nest(accept(MediaType.APPLICATION_JSON).and(contentType(MediaType.APPLICATION_JSON)),
                        route(POST(""), operationLogController::create)
                                .andRoute(DELETE("/{id}"), operationLogController::removeById)
                                .andRoute(GET("/search"), operationLogController::search))).andNest(
                                        path("/statusChangeLog"),
                                        nest(accept(MediaType.APPLICATION_JSON)
                                                .and(contentType(MediaType.APPLICATION_JSON)),
                                                route(POST(""), statusChangeLogController::create)
                                                        .andRoute(GET("/search"), statusChangeLogController::search)));
    }

    @Bean
    public HttpServer httpServer(RouterFunction<?> routerFunction) {
        HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction);
        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
        HttpServer server = HttpServer.create("localhost", Integer.valueOf(environment.getProperty("server.port")));
        server.newHandler(adapter);
        return server;
    }

    @Bean
    public UndertowServletWebServerFactory undertowServletWebServerFactory() {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        factory.addBuilderCustomizers(builder -> {
            builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
                    .setServerOption(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH, true);
        });
        return factory;
    }
}
